package phoenix.web.page_objects;

import java.awt.Dimension;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.testng.TestException;

import phoenix.core.PhoenixManager;
import phoenix.core.base.extensions.PageBaseWebExt;
import phoenix.core.config.extensions.ConfigExt;
import phoenix.core.data_models.TestUserDataModel;
import phoenix.core.data_models.UserProfileDataModel;
import phoenix.core.data_models.UserProfileDataModel.LookingFor;
import phoenix.web.locators.base.SearchPageLocatorsBase;

public class SearchPage extends PageBaseWebExt
{
	/**
	 * Initializes the SearchPage
	 * @param p_manager PhoenixManager instance
	 */
	public SearchPage(PhoenixManager p_manager)
	{
		super(p_manager);
	}

	/**
	 * Gets web elements by site
	 * @return IndexPageLocatorsBase instance
	 */
	public SearchPageLocatorsBase elements()
	{
		switch (manager.testModel().getSiteName())
		{
			case ConfigExt.SITE_ID_CLICKANDFLIRT:
			{
				return new phoenix.web.locators.clickandflirt.SearchPageLocators();
			}
			case ConfigExt.SITE_ID_LOCALSGOWILD:
			{
				return new phoenix.web.locators.localsgowild.SearchPageLocators();
			}
			case ConfigExt.SITE_ID_EBONYFLIRT:
			{
				return new phoenix.web.locators.ebonyflirt.SearchPageLocators();
			}
			case ConfigExt.SITE_ID_CHEECKYLOVERS:
			{
				return new phoenix.web.locators.cheekylovers.SearchPageLocators();
			}
			case ConfigExt.SITE_ID_WILDBUDDIES:
			{
				return new phoenix.web.locators.wildbuddies.SearchPageLocators();
			}
			case ConfigExt.SITE_ID_FLIRT:
			{
				return new phoenix.web.locators.flirt.SearchPageLocators();
			}
			case ConfigExt.SITE_ID_FOREIGNGIRLFRIEND:
			{
				return new phoenix.web.locators.foreigngirlfriend.SearchPageLocators();
			}
			case ConfigExt.SITE_ID_BENAUGHTY:
			{
				return new phoenix.web.locators.benaughty.SearchPageLocators();
			}
			case ConfigExt.SITE_ID_NAUGHTYFEVER:
			{
				return new phoenix.web.locators.naughtyfever.SearchPageLocators();
			}
			case ConfigExt.SITE_ID_MATUREDATING:
			{
				return new phoenix.web.locators.maturedating.SearchPageLocators();
			}
			default:
			{
				return null;
			}
		}
	}

	public void waitForPageLoad()
	{
		wd().waitForPresence(elements().blockUserList, "waitForPageLoad: User results");
	}

	// ////////////////////////////////////////////////////////////////////////////////////////////////

	/**
	 * Check is present or not added friend on page /favorites by given friendLink
	 */
	public boolean isUserPresent(TestUserDataModel p_user) throws Exception
	{
		this.waitForPageLoad();

		if (manager.isFlirt())
		{
			if (!wd().isElementPresent(elements().blockUserList))
			{
				throw new TestException("No search results found " + elements().blockUserList.toString());
			}
		}

		int friends_count = wd().getWebElements(elements().linkScreenname).size();
		if (friends_count == 0)
		{
			throw new TestException("isUserPresent no users have been found");
		}
		else
		{
			log().info("Found " + friends_count + " users at search page");
		}

		if (friends_count != 0)
		{
			for (WebElement linkScreenname : wd().getWebElements(elements().linkScreenname))
			{
				String htmlAttr = linkScreenname.getAttribute("href");

				if (htmlAttr.isEmpty())
				{
					continue;
				}
				String link = manager.string().getSubstringAfter(htmlAttr, "view/id/");

				if (link.equals(p_user.getId()))
				{
					log().info("Found user id: " + p_user.getId());
					return true;
				}
			}

			throw new TestException("Unable to find user " + p_user.getId());
		}

		return false;
	}

	public Dimension avatarSizeTest()
	{
		Dimension imageSize = null;
		imageSize = wd().getImageSize(elements().imgProfile);
		return imageSize;
	}

	public void scrollToBannerUpgrade()
	{
		log().info("SearchPage: scroll to banner Upgrade");

		int scrollCount = 5;
		int loadCount = 0;

		wd().waitForPresence(elements().blockUserList, "Block 'Search results' ");

		while (loadCount < scrollCount)
		{
			if (!wd().isElementDisplayed(elements().blockBannerUpgrade))
			{
				wd().scrollDown();
				loadCount++;
				wd().wait(2);
			}
			else
			{
				break;
			}
		}
	}

	public int getNumberUsersInSearch()
	{
		wd().waitForPresence(elements().blockUserList, "User list");
		WebElement userlist = wd().getWebElement(elements().blockUserList);
		List<WebElement> userprofiles = userlist.findElements(elements().blockUserListItem);
		log().info("Found [" + userprofiles.size() + "] profiles at the page");
		return userprofiles.size();
	}

	public List<WebElement> getUsersInSearch()
	{
		wd().waitForVisibility(elements().blockUserList, "User list");
		WebElement userlist = wd().getWebElement(elements().blockUserList);
		List<WebElement> userprofiles = userlist.findElements(elements().blockUserListItem);
		log().info("Found " + userprofiles.size() + " profiles at the page");

		if (userprofiles.size() == 0)
		{
			throw new TestException("No users have been found at search results");
		}

		return userprofiles;
	}

	public void scrollSearch()
	{
		if (manager.isFGF())
		{
			log().info("Scrolling to last visible User...");
			wd().wait(3);
			wd().scrollToBy(elements().blockUserLastVisible, 10, false);
			wd().wait(6);
		}
		else if (manager.isCNF() || manager.isFlirt() || manager.isLGW() || manager.isWB() || manager.isNF())
		{
			log().info("Scrolling to Upgrade banner...");
			wd().scrollToBy(elements().blockBannerUpgrade, 10, false);
			wd().wait(3);
		}
	}

	public void scrollTo() throws Exception
	{
		wd().waitForVisibility(elements().blockUserList, "User list");

		if (manager.testUser().getMembershipStatus() == 1)
		{
			wd().scrollTo(elements().btnBannerUpgrade);
		}
	}

	public Map<Integer, String[]> getSearchResultsData(LookingFor p_lookingFor) throws Exception
	{
		Map<Integer, String[]> p_searchResults = new HashMap<Integer, String[]>();

		// Wait for user list
		wd().waitForVisibility(elements().blockUserList, "Block user list");

		WebElement userlist = wd().getWebElement(elements().blockUserList);
		List<WebElement> userprofiles = userlist.findElements(elements().blockUserListItem);

		if (userprofiles.size() == 0)
		{
			throw new Exception("No users have been found at search results");
		}

		log().info("Found " + userprofiles.size() + " profiles at the page");

		if (manager.isFlirt())
		{
			wd().jsExec("$('.upgrade-banner').hide()");
		}
		else if (manager.isNF())
		{
			wd().makeElementVisible(elements().blockLocation);
		}

		Integer p_id = 0;
		// Grab all profiles
		for (WebElement elementProfile : userprofiles)
		{
			if (manager.isFlirt())
			{
				wd().scrollWithOffset(elementProfile, 0, -150);
				manager.actionBuilder().mouseOver(elementProfile);
			}

			String p_screenname = getScreen(elementProfile);

			if (p_screenname == "")
			{
				log().info("Do skip for banners at search");
				continue;
			}

			String p_age = this.getAge(elementProfile);
			String p_country = this.getCountry(elementProfile);
			String p_distance = this.getDistance(elementProfile, p_lookingFor);
			String p_userId = this.getUserID(elementProfile);
			p_searchResults.put(p_id, new String[] { p_age, p_distance, p_country, p_screenname, p_userId });
			p_id++;
		}

		log().info("Found " + p_searchResults.size() + " profiles");
		return p_searchResults;
	}

	private String getScreen(WebElement el)
	{
		String p_screenname = el.findElement(elements().txtUserSreenname).getText();

		if (manager.isMD())
		{
			try
			{
				// Do clean up for screen name
				p_screenname.trim();
				Integer position = p_screenname.lastIndexOf("\n");
				if (position != -1)
				{
					p_screenname = p_screenname.substring(0, position);
				}
			}
			catch (Exception p_ex)
			{
				log().errorAndScreen("Unable to cut screen for MD " + p_ex.toString());
			}
		}

		return p_screenname;
	}

	private String getAge(WebElement el)
	{
		String age = el.findElement(elements().txtUserListAge).getText();
		return manager.string().getDigitFromString(age);
	}

	private String getCountry(WebElement el)
	{
		log().info("Getting country value by locator " + elements().txtUserCounty.toString());
		return el.findElement(elements().txtUserCounty).getText();
	}

	private String getDistance(WebElement el, LookingFor p_lookingFor)
	{
		if (manager.isFlirt() || manager.isWB() || manager.isBN())
		{
			return p_lookingFor.distance;
		}
		else if (manager.isNF())
		{
			return this.clearDate(wd().getText(elements().txtUserListDistanse));
		}
		else
		{
			return this.clearDate(el.findElement(elements().txtUserListDistanse).getText());
		}
	}

	private String getUserID(WebElement el)
	{
		if (manager.isWB() || manager.isBN())
		{
			return el.findElement(By.xpath("./..")).getAttribute("data-user-id");
		}
		else if (manager.isMD())
		{
			String uid = el.findElement(By.xpath("//a[@data-screenname]")).getAttribute("href");
			Integer point = uid.lastIndexOf("/");
			return uid.substring(point + 1, uid.length());
		}
		else
		{
			return el.getAttribute("data-user-id");
		}
	}

	/**
	 * Used by getSearchResultsData
	 * @param p_distance
	 * @return
	 */
	private String clearDate(String p_distance)
	{
		if (p_distance.contains("."))
		{
			Integer l_pos = p_distance.indexOf(".");
			return p_distance.substring(0, l_pos);
		}
		else
		{
			return manager.string().getDigitFromString(p_distance);
		}
	}

	public void setSearchLookingFor(LookingFor p_lookingForParams)
	{
		if (manager.isCNF())
		{
			this.advancedSearchLookingFor(p_lookingForParams);
			return;
		}
		else if (manager.isMD() || manager.isNF())
		{
			this.fillSearchForm(p_lookingForParams);
		}
		else
		{
			this.advancedSimpleLookingFor(p_lookingForParams);
		}
	}

	private void fillSearchForm(LookingFor p_lookingForParams)
	{
		// Set gender
		this.setGender(p_lookingForParams);
		this.setAgeFrom(p_lookingForParams);
		this.setAgeTo(p_lookingForParams);
		this.setLocation(p_lookingForParams);
		this.setDistance(p_lookingForParams);
		this.clickSubmit();
		wd().wait(2);
	}

	private void clickSubmit()
	{
		wd().waitForPresence(elements().btnSearch, "Submit search");
		wd().click(elements().btnSearch);
	}

	private void setDistance(LookingFor p_lookingForParams)
	{
		if (manager.isNF())
		{
			wd().waitForPresence(elements().btnRadius, "Radius field");
			wd().click(elements().btnRadius);
			wd().wait(1);
			wd().waitForPresence(By.xpath("//a[@data-list-item='" + p_lookingForParams.distance + "']"), "Dropdown menu");
			wd().click(By.xpath("//a[@data-list-item='" + p_lookingForParams.distance + "']"));
			return;
		}

		wd().waitForPresence(elements().btnRadius, "Radius field");
		wd().click(elements().btnRadius);
		wd().wait(1);
		wd().click(elements().setLocatorByValue(p_lookingForParams.distance, elements().btnRadius));
		wd().wait(1);
	}

	private void setLocation(LookingFor p_lookingForParams)
	{
		if (manager.isNF())
		{
			wd().waitForVisibility(elements().selectLocation, "Field location");
			wd().typeAndClear(elements().selectLocation, p_lookingForParams.location);
			return;
		}

		wd().waitForVisibility(elements().selectLocation, "Field location");
		wd().typeAndClear(elements().selectLocation, p_lookingForParams.location);
		wd().wait(2);
		wd().click(elements().selectLocation);
	}

	private void setAgeTo(LookingFor p_lookingForParams)
	{
		if (manager.isNF())
		{
			wd().waitForPresence(elements().selectAgeTo, "Age from");
			wd().typeAndClear(elements().selectAgeTo, p_lookingForParams.ageTo);
			return;
		}

		wd().waitForPresence(elements().selectAgeTo, "Age from field");
		wd().click(elements().selectAgeTo);
		wd().wait(2);
		wd().scrollToBy(elements().setLocatorByValue(p_lookingForParams.ageTo, elements().selectAgeTo), 5, false);
		wd().wait(1);
		wd().click(elements().setLocatorByValue(p_lookingForParams.ageTo, elements().selectAgeTo));
		wd().wait(1);
	}

	private void setAgeFrom(LookingFor p_lookingForParams)
	{
		if (manager.isNF())
		{
			wd().waitForPresence(elements().selectAgeFrom, "Age from");
			wd().typeAndClear(elements().selectAgeFrom, p_lookingForParams.ageFrom);
			return;
		}

		wd().waitForPresence(elements().selectAgeFrom, "Age from field");
		wd().click(elements().selectAgeFrom);
		wd().wait(2);
		wd().scrollToBy(elements().setLocatorByValue(p_lookingForParams.ageFrom, elements().selectAgeFrom), 5, false);
		wd().wait(1);
		wd().click(elements().setLocatorByValue(p_lookingForParams.ageFrom, elements().selectAgeFrom));
		wd().wait(1);
	}

	private void setGender(LookingFor p_lookingForParams)
	{
		String p_value = (p_lookingForParams.gender.equals("male")) ? "1" : "2";
		wd().waitForPresence(elements().selectGender, "Gender field");

		if (manager.isNF())
		{
			By p_genderLocator = (p_lookingForParams.gender.equals("male")) ? elements().selectGenderM : elements().selectGenderF;
			wd().click(elements().selectGender);
			wd().click(p_genderLocator);
			return;
		}

		wd().click(elements().selectGender);
		wd().wait(2);
		wd().scrollToBy(elements().setLocatorByValue(p_value, elements().selectGender), 5, false);
		wd().wait(1);
		wd().click(elements().setLocatorByValue(p_value, elements().selectGender));
		wd().wait(1);
	}

	private void advancedSearchLookingFor(LookingFor p_lookingForParams)
	{

		wd().waitForPresence(elements().btnEditSearch, "Button 'Edit search' doesn't appear");
		wd().click(elements().btnEditSearch);
		wd().waitForPresence(elements().blockAdvancedSearch, "Block 'Advanced Search' doesn't appear");
		// Location
		wd().waitForVisibility(elements().selectLocation, "Location field");
		wd().click(elements().selectLocation);
		wd().wait(2);
		// Age params
		wd().typeAndClear(elements().selectAgeFrom, p_lookingForParams.ageFrom);
		wd().typeAndClear(elements().selectAgeTo, p_lookingForParams.ageTo);

		wd().typeAndClear(elements().selectLocationValue, manager.testUser().getPostcode());
		wd().wait(2);
		wd().click(elements().btnRadius);
		wd().click(By.linkText(p_lookingForParams.distance));
		wd().wait(1);
		wd().click(elements().selectGender);
		wd().wait(1);
		wd().click(elements().btnSearch);
		wd().wait(3);
	}

	private void advancedSimpleLookingFor(LookingFor p_lookingForParams)
	{
		log().info("Set search parameters...");

		waitForPageLoad();
		wd().waitForPresence(elements().selectAgeFrom, "Option 'Age from' doesn't appear");
		wd().waitForPresence(elements().selectLocationValue, "Option 'Location' doesn't appear");

		wd().typeAndClear(elements().selectAgeFrom, p_lookingForParams.ageFrom);
		wd().wait(2);

		wd().typeAndClear(elements().selectAgeTo, p_lookingForParams.ageTo);
		wd().wait(2);

		wd().click(elements().selectLocation);
		wd().wait(4);

		wd().typeAndClear(elements().selectLocationValue, manager.testUser().getPostcode());
		wd().wait(2);

		this.clickPostCodeOption();
		this.clickDistanceOption(p_lookingForParams);
		wd().click(elements().btnSearch);
		waitForPageLoad();
	}

	private void clickDistanceOption(LookingFor p_lookingForParams)
	{
		By distance;

		if (p_lookingForParams.distance.equals("20"))
		{
			distance = elements().optionRadius20;
		}
		else if (p_lookingForParams.distance.equals("50"))
		{
			distance = elements().optionRadius50;
		}
		else
		{
			distance = elements().optionRadius100;
		}

		if (manager.isFlirt())
		{
			wd().click(elements().selectLocation);
			wd().wait(4);
			return;
		}

		if (manager.isBN() || manager.isWB())
		{
			wd().click(elements().selectLocation);
			wd().wait(4);
		}

		wd().click(distance);
		wd().wait(2);
	}

	private void clickPostCodeOption()
	{
		wd().click(elements().btnByPostcode(manager.testUser().getPostcode()));
	}

	public void closePopup()
	{
		if (wd().isElementDisplayed(elements().btnClosePopup))
		{
			log().info("Popup is visible after page loading. Click on 'close' popup button");
			wd().click(elements().btnClosePopup);
		}
	}

	public void closeCoregPopup()
	{
		if (wd().isElementDisplayed(elements().btnCloseCoregPopup))
		{
			log().info("Popup Coreg is visible after page loading. Click on 'close' popup button");
			wd().click(elements().btnCloseCoregPopup);
		}
	}

	public void closePopUpAlert()
	{
		if (wd().isElementPresent(elements().btnClosePopupAlert))
		{
			log().info("pop up alert notification");
			wd().waitForPresence(elements().btnClosePopupAlert, "Popup close button");
			wd().click(elements().btnClosePopupAlert);
		}
	}

	public void closeAllPopUps()
	{
		wd().wait(5);
		this.closeCoregPopup();
		this.closePopup();
	}

	/**
	 * Opens Messanger in search list by user Id
	 * @param p_user
	 */
	public void openMessangerByIdFromSearch(TestUserDataModel p_user)
	{
		if (manager.isCNF())
		{
			this.openMessengerByIdCnf(p_user);
		}
		else if (manager.isFlirt())
		{
			this.openMessengerByIdFlirt(p_user);
		}
		else if (manager.isWB())
		{
			this.openMessengerByIdWb(p_user);
		}
		else if (manager.isBN())
		{
			this.openMessengerByIdBn(p_user);
		}
	}

	private void openMessengerByIdBn(TestUserDataModel p_user)
	{
		wd().waitForVisibility(elements().btnByUserMessenger(p_user), "Messenger by Id");
		wd().click(elements().btnByUserMessenger(p_user));
	}

	private void openMessengerByIdWb(TestUserDataModel p_user)
	{
		List<WebElement> userprofiles = getUsersInSearch();
		Integer pi = 1;
		for (WebElement elementProfile : userprofiles)
		{
			String p_userId = elementProfile.findElement(By.xpath("./..")).getAttribute("data-user-id");
			if (p_userId.equals(p_user.getId()))
			{
				log().info("Clicking by ID on " + elements().btnUserMessengerOpen(pi).toString());
				elementProfile.findElement(elements().btnUserMessengerOpen(pi)).click();
				wd().wait(3);
				return;
			}
			pi++;
		}
		log().errorAndScreen("Unable to find profile by ID on this page");
	}

	private void openMessengerByIdCnf(TestUserDataModel p_user)
	{
		wd().waitForPresence(elements().btnMessengerOpen(p_user), "Messenger button by ID");
		wd().click(elements().btnMessengerOpen(p_user));
	}

	private void openMessengerByIdFlirt(TestUserDataModel p_user)
	{
		List<WebElement> userprofiles = getUsersInSearch();
		for (WebElement elementProfile : userprofiles)
		{
			wd().flashWebElement(elementProfile);
			wd().scrollWithOffset(elementProfile, 0, -150);
			manager.actionBuilder().mouseOver(elementProfile);
			String p_userId = elementProfile.getAttribute("data-user-id");

			if (p_userId.equals(p_user.getId()))
			{
				elementProfile.findElement(elements().btnUserMessenger).click();
				wd().wait(3);
				return;
			}
		}
	}

	public void clickBannerUpgrade()
	{
		log().info("SearchPage: click banner Upgrade");
		wd().waitForPresence(elements().btnBanner, "Button 'Banner Upgrade' doesn't appear");
		wd().click(elements().btnBanner);
	}

	public boolean isPopUpAlertVisible()
	{
		return wd().isElementDisplayed(elements().blockPopUpAlert);
	}
}
